/** \file    spirit.inl
  * \brief   Internal inline functions declared with the implementation.
  * \date    2003
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/xml/spirit/src/spirit.inl,v 1.1 2004/03/22 09:24:09 cscom1r4 Exp $
  */

#include <algorithm>
#include <xtd/functional>

namespace xml {

bool valid_name(const string & name);

inline spirit::element::element(element * p, const string & t) :
	_parent(p),
	_tag(t)
{
	if (!valid_name(t))
		throw invalid_name();
}

inline spirit::element::~element()
{
	std::for_each(_children.begin(), _children.end(), xtd::deleter());
	_children.clear();
}

inline spirit::element * spirit::element::parent()
{
	return _parent;
}

inline const string & spirit::element::tag() const
{
	return _tag;
}

inline bool spirit::element::get_attribute(const string & name, string & value) const
{
	attrs_type::const_iterator i = _attrs.find(name);
	if (i == _attrs.end())
		return false;
	value = i->second;
	return true;
}

inline void spirit::element::set_attribute(const string & name, const string & value)
{
	attrs_type::iterator i = _attrs.lower_bound(name);
	if (i == _attrs.end() || i->first != name) {
		if (!valid_name(name))
			throw invalid_name();
		_attrs.insert(i, attrs_type::value_type(name, value));
	}
	else
		i->second = value;
}

inline handle spirit::element::create_child(const string & tag)
{
	_children.push_back(new element(this, tag));
	return _children.back();
}

inline void spirit::element::clear(bool attr, bool children)
{
	if (attr)
		_attrs.clear();
	if (children)
		this->~element();
}

inline void spirit::element::erase()
{
	assert(_parent);
	_parent->erase(this);
}

inline void spirit::element::erase(element * child)
{
	delete child;
	_children.erase(std::find(_children.begin(), _children.end(), child));
}

} //namespace xml
